package com.clj.securityoauthcustom.handler;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class OAuthenticationSucessHandler implements AuthenticationSuccessHandler{

	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private ClientDetailsService clientDetailsService;
	@Autowired
	private AuthorizationServerTokenServices  autorizationServerTokenServices;
	
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
		//1.从请求头中获取ClientId
		String header = request.getHeader("Authorization");
		if(header == null || !header.startsWith("Basic ")) {
			throw new UnapprovedClientAuthenticationException("请求头中无client信息");
		}
		
		String[] tokens=this.extractAndDecodeHeader(header, request);
		String clientId = tokens[0];
		String clientSecret=tokens[1];
		
		TokenRequest tokenRequest=null;
		
		//2.通过ClientDetailsService 获取ClientDetails
		ClientDetails clientDetails=clientDetailsService.loadClientByClientId(clientId);
		
		//3.校验ClientId和ClientSecret的正确性
		 if (clientDetails == null) {
	            throw new UnapprovedClientAuthenticationException("clientId:" + clientId + "对应的信息不存在");
	        } else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
	            throw new UnapprovedClientAuthenticationException("clientSecret不正确");
	        } else {
	            // 4. 通过 TokenRequest构造器生成 TokenRequest
	            tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
	        }
		 //5.通过TokenRequest的createOAuth2Request方法获取OAuth2Request
		 OAuth2Request oAuth2Request =tokenRequest.createOAuth2Request(clientDetails);
		// 6. 通过 Authentication和 OAuth2Request构造出 OAuth2Authentication
	        OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);

	        // 7. 通过 AuthorizationServerTokenServices 生成 OAuth2AccessToken
	        OAuth2AccessToken token = autorizationServerTokenServices.createAccessToken(auth2Authentication);

	        // 8. 返回 Token
	        log.info("登录成功");
	        response.setContentType("application/json;charset=UTF-8");
	        response.getWriter().write(new ObjectMapper().writeValueAsString(token));
		 
		
		
		
	}

	private String[] extractAndDecodeHeader(String header, HttpServletRequest request) {
		 byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);

	        byte[] decoded;
	        try {
	            decoded = Base64.getDecoder().decode(base64Token);
	        } catch (IllegalArgumentException var7) {
	            throw new BadCredentialsException("Failed to decode basic authentication token");
	        }

	        String token = new String(decoded, StandardCharsets.UTF_8);
	        int delim = token.indexOf(":");
	        if (delim == -1) {
	            throw new BadCredentialsException("Invalid basic authentication token");
	        } else {
	            return new String[]{token.substring(0, delim), token.substring(delim + 1)};
	        }
	}

}
